(*$S+*)
UNIT NUMBER2;

INTERFACE

USES {$U H19UTIL.CODE} H19UTIL;

TYPE    NUMBERTYPE = (DEC,HEX,OCT,BIN);
        HEXNUM = PACKED ARRAY [1..4] OF 0..15;
        BINNUM = PACKED ARRAY [0..15] OF 0..1;
        OCTNUM = PACKED RECORD
                   O5,O4,O3,O2,O1: 0..7;
                   O6 : 0..1;
                 END;
        CHAMELEON = RECORD CASE NUMBERTYPE OF
                     DEC : (INT : INTEGER);
                     HEX : (HEXINT : HEXNUM);
                     OCT : (OCTINT : OCTNUM);
                     BIN : (BININT : BINNUM)
                  END;

VAR     OCTAL,BINARY,HEXA : BOOLEAN;

PROCEDURE WRITEHEX (INTG : INTEGER);

PROCEDURE WRITEFLIP (INTG : INTEGER);

PROCEDURE WRITEOCTAL (INTG : INTEGER);

PROCEDURE WRITEBIN (INTG : INTEGER);

PROCEDURE GETHEX (VAR DATA : INTEGER);

PROCEDURE GETFLIP (VAR DATA : INTEGER);

PROCEDURE GETOCTAL (VAR DATA : INTEGER);

PROCEDURE GETBINARY (VAR DATA : INTEGER);

IMPLEMENTATION

VAR     LEN : INTEGER;

PROCEDURE WRITEHEX(* INTG : INTEGER *);
  VAR   N : INTEGER;
        NUMBER : CHAMELEON;
  BEGIN
    NUMBER.INT := INTG;
    WITH NUMBER DO
      BEGIN
        FOR N := 4 DOWNTO 1 DO
          BEGIN
            IF (HEXINT[N] <= 9) THEN WRITE(HEXINT[N])
              ELSE WRITE(CHR(HEXINT[N] + ORD('A') - 10))
          END
      END
  END;
  
PROCEDURE WRITEFLIP(* INTG : INTEGER *);
  VAR   N : INTEGER;
        NUMBER : CHAMELEON;
  BEGIN
    NUMBER.INT := INTG;
    WITH NUMBER DO
      BEGIN
        FOR N := 2 DOWNTO 1 DO
          BEGIN
            IF (HEXINT[N] <= 9) THEN WRITE(HEXINT[N])
              ELSE WRITE(CHR(HEXINT[N] + ORD('A') - 10))
          END;
        FOR N := 4 DOWNTO 3 DO
          BEGIN
            IF (HEXINT[N] <= 9) THEN WRITE(HEXINT[N])
              ELSE WRITE(CHR(HEXINT[N] + ORD('A') - 10))
          END
      END
  END;
  
PROCEDURE WRITEOCTAL(* INTG : INTEGER *);
  VAR   N : INTEGER;
        NUMBER : CHAMELEON;
  BEGIN
    NUMBER.INT := INTG;
    WITH NUMBER.OCTINT DO WRITE(O6,O5,O4,O3,O2,O1)
  END;
  
PROCEDURE WRITEBIN (* INTG : INTEGER *);
  VAR   N : INTEGER;
        NUMBER : CHAMELEON;
  BEGIN
    NUMBER.INT := INTG;
    WITH NUMBER DO FOR N := 15 DOWNTO 0 DO WRITE(BININT[N])
  END;
  
PROCEDURE ERRHNDLR(VAR DATA : INTEGER);
  CONST BELL = 7;
  BEGIN
    CLEARSPACE(0,0,80);
    WRITE(CHR(BELL),'Improper number. Retype.');
    CLEARSPACE(XCUR,YCUR,LEN);    (*XCUR,YCUR are globals*)
    IF OCTAL THEN GETOCTAL(DATA)
      ELSE IF BINARY THEN GETBINARY(DATA)
        ELSE IF HEXA THEN GETHEX(DATA)
          ELSE GETFLIP(DATA);
    SAVECURSOR(XCUR,YCUR);
    CLEARSPACE(0,0,80);
    GOTOXY(XCUR,YCUR);
    IF OCTAL THEN EXIT(GETOCTAL)
      ELSE IF BINARY THEN EXIT(GETBINARY)
        ELSE IF HEXA THEN EXIT(GETHEX)
          ELSE EXIT(GETFLIP)
  END;
    
PROCEDURE GETHEX(*VAR DATA : INTEGER*);
  VAR   I : INTEGER;
        NUMBER : CHAMELEON;
        STR : STRING;

  BEGIN
    OCTAL := FALSE;
    BINARY := FALSE;
    HEXA := TRUE;
    SAVECURSOR(XCUR,YCUR);
    READLN(STR);
    LEN := LENGTH(STR);
    FOR I := 1 TO LEN DO IF NOT (STR[I] IN ['0'..'9','A'..'F']) THEN ERRHNDLR(DATA);
    IF (LEN > 4) THEN ERRHNDLR(DATA);
    FOR I := 1 TO (4-LEN) DO STR := CONCAT('0',STR);
    WITH NUMBER DO FOR I := 4 DOWNTO 1 DO
        IF STR[I] IN ['0'..'9'] THEN HEXINT[5-I] := ORD(STR[I]) - ORD('0')
          ELSE HEXINT[5-I] := ORD(STR[I]) - ORD('A') + 10;
    DATA := NUMBER.INT
  END;
  
PROCEDURE GETFLIP(*VAR DATA : INTEGER*);
  VAR   I : INTEGER;
        NUMBER : CHAMELEON;
        FLIPSTR,STR : STRING;

  BEGIN
    OCTAL := FALSE;
    BINARY := FALSE;
    HEXA := FALSE;
    STR := '1234';
    SAVECURSOR(XCUR,YCUR);
    READLN(FLIPSTR);
    LEN := LENGTH(FLIPSTR);
    FOR I := 1 TO LEN DO IF NOT (FLIPSTR[I] IN ['0'..'9','A'..'F'])
       THEN ERRHNDLR(DATA);
    IF (LEN > 4) THEN ERRHNDLR(DATA);
    FOR I := 1 TO (4-LEN) DO FLIPSTR := CONCAT('0',FLIPSTR);
    STR[1] := FLIPSTR[3];
    STR[2] := FLIPSTR[4];
    STR[3] := FLIPSTR[1];
    STR[4] := FLIPSTR[2];
    WITH NUMBER DO FOR I := 4 DOWNTO 1 DO
        IF STR[I] IN ['0'..'9'] THEN HEXINT[5-I] := ORD(STR[I]) - ORD('0')
          ELSE HEXINT[5-I] := ORD(STR[I]) - ORD('A') + 10;
    DATA := NUMBER.INT
  END;
  
PROCEDURE GETOCTAL(*VAR DATA : INTEGER*);
  VAR   I : INTEGER;
        NUMBER : CHAMELEON;
        STR : STRING;
  BEGIN
    OCTAL := TRUE;
    BINARY := FALSE;
    HEXA := FALSE;
    SAVECURSOR(XCUR,YCUR);
    READLN(STR);
    LEN := LENGTH(STR);
    FOR I := 1 TO LEN DO IF NOT (STR[I] IN ['0'..'7']) THEN ERRHNDLR(DATA);
    IF (LEN > 6) THEN ERRHNDLR(DATA);
    FOR I := 1 TO (6-LEN) DO STR := CONCAT('0',STR);
    IF (STR > '177777') THEN ERRHNDLR(DATA);
    WITH NUMBER.OCTINT DO
      BEGIN
        O6 := ORD(STR[1]) - ORD('0');
        O5 := ORD(STR[2]) - ORD('0');
        O4 := ORD(STR[3]) - ORD('0');
        O3 := ORD(STR[4]) - ORD('0');
        O2 := ORD(STR[5]) - ORD('0');
        O1 := ORD(STR[6]) - ORD('0')
      END;
    DATA := NUMBER.INT
  END;
  
PROCEDURE GETBINARY(*VAR DATA : INTEGER*);
  VAR   I : INTEGER;
        NUMBER : CHAMELEON;
        STR : STRING;
  BEGIN
    OCTAL := FALSE;
    BINARY := TRUE;
    HEXA := FALSE;
    SAVECURSOR(XCUR,YCUR);
    READLN(STR);
    LEN := LENGTH(STR);
    FOR I := 1 TO LEN DO IF NOT (STR[I] IN ['0','1']) THEN ERRHNDLR(DATA);
    IF (LEN > 16) THEN ERRHNDLR(DATA);
    FOR I := 1 TO (16-LEN) DO STR := CONCAT('0',STR);
    WITH NUMBER DO FOR I := 15 DOWNTO 0 DO BININT[I] := ORD(STR[16-I]) - ORD('0');
    DATA := NUMBER.INT
  END;
END. (* of unit *)
